package com.numberone.iotplatform.controller;

import com.numberone.iotplatform.dto.JwtResponse;
import com.numberone.iotplatform.dto.LoginRequest;
import com.numberone.iotplatform.dto.MessageResponse;
import com.numberone.iotplatform.dto.SignupRequest;
import com.numberone.iotplatform.entity.ERole;
import com.numberone.iotplatform.entity.Role;
import com.numberone.iotplatform.entity.User;
import com.numberone.iotplatform.repository.RoleRepository;
import com.numberone.iotplatform.repository.UserRepository;
import com.numberone.iotplatform.security.jwt.JwtUtils;
import com.numberone.iotplatform.security.services.UserDetailsImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 认证控制器，处理用户登录和注册请求。
 * 所有代码已确认兼容 JDK 1.8。
 */
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/auth")
public class AuthController {

    private static final Logger log = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    PasswordEncoder encoder;

    @Autowired
    JwtUtils jwtUtils;

    /**
     * 用户登录，生成 JWT 令牌。
     */
    @PostMapping("/login")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);

        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        List<String> roles = userDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());

        log.info("User logged in: {}", userDetails.getUsername());
        return ResponseEntity.ok(new JwtResponse(jwt,
                userDetails.getId(),
                userDetails.getUsername(),
                roles));
    }

    /**
     * 用户注册，创建新用户并分配角色。
     */
    @PostMapping("/signup")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
        String username = signUpRequest.getUsername();
        List<User> existingUsers = userRepository.findByUsername(username);
        if (!existingUsers.isEmpty()) {
            log.warn("Username already taken: {}", username);
            return ResponseEntity
                    .badRequest()
                    .body(new MessageResponse("Error: Username is already taken!"));
        }

        // 创建新用户
        User user = new User(signUpRequest.getUsername(),
                encoder.encode(signUpRequest.getPassword()),
                signUpRequest.getPhone());

        Set<String> strRoles = signUpRequest.getRole();
        Set<Role> roles = new HashSet<>();

        if (strRoles == null) {
            List<Role> userRoles = roleRepository.findByName(ERole.ROLE_USER);
            if (userRoles.isEmpty()) {
                log.error("Role not found: {}", ERole.ROLE_USER);
                throw new RuntimeException("Error: Role is not found.");
            } else if (userRoles.size() > 1) {
                log.warn("Multiple roles found for name: {}. Using first role.", ERole.ROLE_USER);
            }
            roles.add(userRoles.get(0));
        } else {
            for (String role : strRoles) {
                ERole eRole;
                switch (role.toLowerCase()) {
                    case "admin":
                        eRole = ERole.ROLE_ADMIN;
                        break;
                    case "operator":
                        eRole = ERole.ROLE_OPERATOR;
                        break;
                    default:
                        eRole = ERole.ROLE_USER;
                }
                List<Role> foundRoles = roleRepository.findByName(eRole);
                if (foundRoles.isEmpty()) {
                    log.error("Role not found: {}", eRole);
                    throw new RuntimeException("Error: Role is not found: " + eRole);
                } else if (foundRoles.size() > 1) {
                    log.warn("Multiple roles found for name: {}. Using first role.", eRole);
                }
                roles.add(foundRoles.get(0));
            }
        }

        user.setRoles(roles);
        userRepository.save(user);
        log.info("User registered successfully: {}", username);
        return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
    }
}